package com.ctshk.rpc.cms.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.RedisConstants;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SupplierStatus;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.redis.KeyUtil;
import com.ctshk.rpc.cms.constant.CmsConstant;
import com.ctshk.rpc.cms.dto.NoticeDTO;
import com.ctshk.rpc.cms.dto.NoticePositionDTO;
import com.ctshk.rpc.cms.dto.NoticePositionListDTO;
import com.ctshk.rpc.cms.entity.Notice;
import com.ctshk.rpc.cms.entity.NoticePosition;
import com.ctshk.rpc.cms.entity.NoticePositionUser;
import com.ctshk.rpc.cms.mapper.NoticeMapper;
import com.ctshk.rpc.cms.mapper.NoticePositionMapper;
import com.ctshk.rpc.cms.mapper.NoticePositionUserMapper;
import com.ctshk.rpc.cms.req.*;
import com.ctshk.rpc.cms.service.INoticePositionService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 公告位置管理表 服务实现类
 * </p>
 *
 * @author LiZhiming
 * @since 2021-04-23
 */
@DubboService
public class NoticePositionServiceImpl extends ServiceImpl<NoticePositionMapper, NoticePosition> implements INoticePositionService {

    @Autowired
    private NoticePositionUserMapper noticePositionUserMapper;

    @DubboReference
    private ISysUserService sysUserService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private NoticeMapper noticeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(NoticePositionAddReq req, TokenUser tu) {
        QueryWrapper<NoticePosition> qw = new QueryWrapper<>();
        qw.lambda().eq(NoticePosition::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(NoticePosition::getNoticeCode, req.getNoticeCode());
        if (baseMapper.selectCount(qw) > 0) {
            return Result.failed(SystemError.CMS_23003);
        }
        NoticePosition noticePosition = EntityUtil.copy(req, NoticePosition.class);
        LocalDateTime now = LocalDateTime.now();
        Long id = IdWorker.getId();
        noticePosition.setId(id);
        noticePosition.setCreateId(tu.getId());
        noticePosition.setGmtCreate(now);
        noticePosition.setIsDeleted(IsDeletedCode.NO.getCode());
        int insert = baseMapper.insert(noticePosition);
        //公告位新增成功后新增操作人
        if (insert > 0 && CollectionUtils.isNotEmpty(req.getNoticePositionUsers())) {
            for (NoticePositionUserReq npur : req.getNoticePositionUsers()) {
                NoticePositionUser copy = EntityUtil.copy(npur, NoticePositionUser.class);
                copy.setId(IdWorker.getId());
                copy.setNoticePositionId(noticePosition.getId());
                copy.setCreateId(tu.getId());
                copy.setGmtCreate(now);
                copy.setIsDeleted(IsDeletedCode.NO.getCode());
                noticePositionUserMapper.insert(copy);
            }
            return Result.success(id);
        }
        return Result.failed(SystemError.CMS_23000);
    }

    @Override
    public Result<List<NoticePositionDTO>> getSelectList() {
        QueryWrapper<NoticePosition> qw = new QueryWrapper<>();
        qw.lambda().eq(NoticePosition::getIsDeleted, IsDeletedCode.NO.getCode());
        List<NoticePosition> noticePositions = baseMapper.selectList(qw);
        return Result.success(EntityUtil.copyList(noticePositions, NoticePositionDTO.class));
    }

    @Override
    public Result<PageResponse<NoticePositionDTO>> getSelectList2(SelectAllQueryReq req) {
        Page<NoticePosition> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<NoticePosition> qw = new QueryWrapper<>();
        qw.lambda()
                .select(NoticePosition::getId, NoticePosition::getNoticeName)
                .eq(NoticePosition::getIsDeleted, IsDeletedCode.NO.getCode());
        Page<NoticePosition> iPage = baseMapper.selectPage(page, qw);
        List<NoticePositionDTO> ccs = EntityUtil.copyList(iPage.getRecords(), NoticePositionDTO.class);
        PageResponse<NoticePositionDTO> ccsDto = new PageResponse<>(ccs,
                iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() *
                iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        return Result.success(ccsDto);
    }

    @Override
    public PageResponse<NoticePositionListDTO> getList(NoticePositionQueryReq req) {
        Page<NoticePosition> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<NoticePosition> qw = new QueryWrapper<>();
        qw.lambda().eq(req.getNoticeCode() != null, NoticePosition::getNoticeCode, req.getNoticeCode())
                .eq(req.getNoticeName() != null, NoticePosition::getNoticeName, req.getNoticeName())
                .eq(req.getNoticeType() != null, NoticePosition::getNoticeType, req.getNoticeType())
                .eq(NoticePosition::getIsDeleted, IsDeletedCode.NO.getCode());
        Page<NoticePosition> iPage = baseMapper.selectPage(page, qw);
        List<NoticePosition> records = iPage.getRecords();
        List<NoticePositionListDTO> bpldtos = new ArrayList<>();
        //填充公告操作人
        QueryWrapper<NoticePositionUser> qwnpu = new QueryWrapper<>();
        for (NoticePosition bp : records) {
            NoticePositionListDTO copy = EntityUtil.copy(bp, NoticePositionListDTO.class);
            UserDTO userDTO = sysUserService.loadUserInfo(bp.getCreateId(), 1);
            if (userDTO != null) {
                copy.setUserName(userDTO.getCnSurname() + userDTO.getCnName());
            }
            qwnpu.clear();
            qwnpu.lambda().eq(NoticePositionUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(NoticePositionUser::getNoticePositionId, copy.getId());
            List<NoticePositionUser> bpus = noticePositionUserMapper.selectList(qwnpu);
            if (CollectionUtils.isNotEmpty(bpus)) {
                List<NoticePositionUserReq> bpusdtos = EntityUtil.copyList(bpus, NoticePositionUserReq.class);
                copy.setNoticePositionUsers(bpusdtos);
            }
            bpldtos.add(copy);
        }
        PageResponse<NoticePositionListDTO> bppr = new PageResponse<>(bpldtos,
                iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() *
                iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        return bppr;
    }

    @Override
    public Result<NoticePositionListDTO> getNoticePositionById(Long id) {
        ValueOperations ops = redisTemplate.opsForValue();
        //先取缓存不存在就重新查
        String opsNpl = (String) ops.get(CmsConstant.CMS_NOTICE_REDIS_KEY + id.toString());
        if (StringUtils.isNotBlank(opsNpl)) {
            JSONObject jsonObject = JSON.parseObject(opsNpl);
            NoticePositionListDTO nplDTO = jsonObject.toJavaObject(NoticePositionListDTO.class);
            return Result.success(nplDTO);
        }
        QueryWrapper<NoticePosition> qw = new QueryWrapper<>();
        qw.lambda().eq(NoticePosition::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(NoticePosition::getId, id).orderByDesc(NoticePosition::getGmtCreate).last("limit 1");
        NoticePosition noticePosition = baseMapper.selectOne(qw);
        if (noticePosition != null) {
            NoticePositionListDTO npl = EntityUtil.copy(noticePosition, NoticePositionListDTO.class);
            //填充公告
            QueryWrapper<Notice> qwn = new QueryWrapper<>();
            qwn.lambda().eq(Notice::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(Notice::getStatus, SupplierStatus.ENABLE.getCode())
                    .eq(Notice::getNoticePositionId, noticePosition.getId());
            List<Notice> notices = noticeMapper.selectList(qwn);
            if (notices != null && notices.size() > 0) {
                List<NoticeDTO> result = EntityUtil.copyList(notices, NoticeDTO.class);
                npl.setNoticeDTOS(result);
            }
            //填充公告操作人
            QueryWrapper<NoticePositionUser> qwnpu = new QueryWrapper<>();
            qwnpu.lambda().eq(NoticePositionUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(NoticePositionUser::getNoticePositionId, noticePosition.getId());
            List<NoticePositionUser> bpus = noticePositionUserMapper.selectList(qwnpu);
            if (CollectionUtils.isNotEmpty(bpus)) {
                List<NoticePositionUserReq> bpusdtos = EntityUtil.copyList(bpus, NoticePositionUserReq.class);
                npl.setNoticePositionUsers(bpusdtos);
            }
            if (npl != null) {
                //存一个缓存
                ops.set(CmsConstant.CMS_NOTICE_REDIS_KEY + id.toString(), JSONObject.toJSONString(npl));
            }
            return Result.success(npl);
        } else {
            return Result.failed(SystemError.CMS_23001);
        }
    }

    @Override
    public Result<NoticePositionListDTO> getNoticePositionByCode(String code) {
        ValueOperations ops = redisTemplate.opsForValue();
        //先取缓存不存在就重新查
        String opsNpl = (String) ops.get(CmsConstant.CMS_NOTICE_REDIS_KEY + code);
        if (StringUtils.isNotBlank(opsNpl)) {
            JSONObject jsonObject = JSON.parseObject(opsNpl);
            NoticePositionListDTO nplDTO = jsonObject.toJavaObject(NoticePositionListDTO.class);
            return Result.success(nplDTO);
        }
        QueryWrapper<NoticePosition> qw = new QueryWrapper<>();
        qw.lambda().eq(NoticePosition::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(NoticePosition::getNoticeCode, code).orderByDesc(NoticePosition::getGmtCreate).last("limit 1");
        NoticePosition noticePosition = baseMapper.selectOne(qw);
        if (noticePosition != null) {
            NoticePositionListDTO npl = EntityUtil.copy(noticePosition, NoticePositionListDTO.class);
            //填充公告
            QueryWrapper<Notice> qwn = new QueryWrapper<>();
            qwn.lambda().eq(Notice::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(Notice::getStatus, SupplierStatus.ENABLE.getCode())
                    .eq(Notice::getNoticePositionId, noticePosition.getId());
            List<Notice> notices = noticeMapper.selectList(qwn);
            if (notices != null && notices.size() > 0) {
                List<NoticeDTO> result = EntityUtil.copyList(notices, NoticeDTO.class);
                npl.setNoticeDTOS(result);
            }
            //填充公告操作人
            QueryWrapper<NoticePositionUser> qwnpu = new QueryWrapper<>();
            qwnpu.lambda().eq(NoticePositionUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(NoticePositionUser::getNoticePositionId, noticePosition.getId());
            List<NoticePositionUser> bpus = noticePositionUserMapper.selectList(qwnpu);
            if (CollectionUtils.isNotEmpty(bpus)) {
                List<NoticePositionUserReq> bpusdtos = EntityUtil.copyList(bpus, NoticePositionUserReq.class);
                npl.setNoticePositionUsers(bpusdtos);
            }
            if (npl != null) {
                //存一个缓存
                ops.set(CmsConstant.CMS_NOTICE_REDIS_KEY + code, JSONObject.toJSONString(npl),1, TimeUnit.DAYS);
            }
            return Result.success(npl);
        } else {
            return Result.failed(SystemError.CMS_23001);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result update(NoticePositionUpdateReq req, TokenUser tu) {
        NoticePosition np = EntityUtil.copy(req, NoticePosition.class);
        LocalDateTime now = LocalDateTime.now();
        np.setModifiedId(tu.getId());
        np.setGmtModified(now);
        int i = baseMapper.updateById(np);
        //更新修改的操作人(操作人这种变动频繁的就不使用逻辑删除了，直接干掉从新添加)
        if (i > 0) {
            if (CollectionUtils.isNotEmpty(req.getNoticePositionUsers())) {
                QueryWrapper<NoticePositionUser> qw = new QueryWrapper<>();
                qw.lambda().eq(NoticePositionUser::getNoticePositionId, req.getId());
                noticePositionUserMapper.delete(qw);
                //将新的操作人添加入库
                List<NoticePositionUserReq> npurs = req.getNoticePositionUsers();
                for (NoticePositionUserReq bpur : npurs) {
                    NoticePositionUser copy = EntityUtil.copy(bpur, NoticePositionUser.class);
                    copy.setId(IdWorker.getId());
                    copy.setNoticePositionId(req.getId());
                    copy.setCreateId(tu.getId());
                    copy.setGmtCreate(now);
                    copy.setIsDeleted(IsDeletedCode.NO.getCode());
                    noticePositionUserMapper.insert(copy);
                }
            }
            //做了修改操作如果存在这个缓存就清除缓存
            Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_NOTICE_REDIS_KEY));
            if (CollUtil.isNotEmpty(keysRecommend)) {
                redisTemplate.delete(keysRecommend);
            }
            return Result.success(req.getId());
        }
        return Result.failed(SystemError.CMS_23002);
    }
}
